/* 
 *  Copyright (c) 2011—2013 Panguso.com. All rights reserved. 
 *  File Name:  XESReverse.java                                      
 *  File Contents Outline :  XES反转
 *  File  Create Date:   2012年7月30日
 *  File Version#: Revision#: #1                  
 *  File  Latest Modify Date : 2013年1月16日
 *  File Author :  bachuan@panguso.com
 */
package cn.edu.thu.log.xes;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;

import org.deckfour.xes.extension.std.XConceptExtension;
import org.deckfour.xes.extension.std.XTimeExtension;
import org.deckfour.xes.factory.XFactory;
import org.deckfour.xes.factory.XFactoryRegistry;
import org.deckfour.xes.info.XLogInfo;
import org.deckfour.xes.info.XLogInfoFactory;
import org.deckfour.xes.model.XAttribute;
import org.deckfour.xes.model.XEvent;
import org.deckfour.xes.model.XLog;
import org.deckfour.xes.model.XTrace;

import cn.edu.thu.log.util.Format;
import cn.edu.thu.log.util.PanGuConstants;
import cn.edu.thu.log.web.service.XESReadService;
import cn.edu.thu.log.web.service.impl.XESReadServiceImpl;

public class XESReverse {

    ArrayList<String> originalLogLocationList;
    ArrayList<String> traceNameList;
    ArrayList<XTrace> traceList;// not used
    /**
     * map of laster arrival time in one case
     */
    Hashtable<String, String> lastestArrivalMap;
    /**
     * map of earliest arrival time . one case
     */
    Hashtable<String, String> earliestArrivalMap;

    public XESReverse() {
        originalLogLocationList = new ArrayList<String>();
        traceNameList = new ArrayList<String>();
        lastestArrivalMap = new Hashtable<String, String>();
        earliestArrivalMap = new Hashtable<String, String>();
    }

    /**
     * find xes files by name and address(this address is a filePath)
     *
     * @param sourcePath address or ip
     * @param name name of xes
     * @return merged log
     */
    public void reverse(String xesName) {
        //读取数据库中的xes，得到XLog
        XFactory factory = XFactoryRegistry.instance().currentDefault();
      //  XESReadService reader = new XESReadServiceImpl(xesName);
            XESReadService reader =  XESReadServiceImpl.instance();//change
            reader.setName(xesName);
            reader.setRandom(false);
        //遍历XES（多个Branch）
        while (reader.hasNext()) {
            XLog log = reader.next();
            //遍历一个XLog
            reverseOneXLog(log);
        }
    }

    private void reverseOneXLog(XLog eachLog) {
        for (XTrace eachTrace : eachLog) {
            String traceNameBranch = eachTrace.getAttributes().get(
                    XConceptExtension.KEY_NAME).toString();

            // String traceName = traceNameBranch.substring(0,
            // traceNameBranch
            // .lastIndexOf(","));
            if (!traceNameList.contains(traceNameBranch)) {
                traceNameList.add(traceNameBranch);
                lastestArrivalMap.put(traceNameBranch, "");
                earliestArrivalMap.put(traceNameBranch, "");
                int evetnSize = 0;
                for (XEvent eachEvent : eachTrace) {
                    evetnSize++;
                }
      //          System.out.print("\nevent size:" + evetnSize);

            } else {
            }
            for (XEvent eachEvent : eachTrace) {



                String originalLogLocation = eachEvent.getAttributes().get(PanGuConstants.LOGPATH_ATTRIBUTE).toString();

                if (!originalLogLocationList.contains(originalLogLocation)) {
                    originalLogLocationList.add(originalLogLocation);
                }

                // time
                String eventTime = eachEvent.getAttributes().get(
                        XTimeExtension.KEY_TIMESTAMP).toString().substring(0, 19);

                if (lastestArrivalMap.get(traceNameBranch).compareTo(eventTime) < 0) {
                    lastestArrivalMap.put(traceNameBranch, eventTime);
                }
                if (earliestArrivalMap.get(traceNameBranch) == "" || earliestArrivalMap.get(traceNameBranch).compareTo(eventTime) > 0) {
                    earliestArrivalMap.put(traceNameBranch, eventTime);
                }

            }
        }
    }

    public ArrayList<String> getOriginalLogLocationList() {
        return originalLogLocationList;
    }

    public ArrayList<String> getTraceNameList() {
        return traceNameList;
    }

    public void setTraceNameList(ArrayList<String> traceNameList) {
        this.traceNameList = traceNameList;
    }

    public void generateFitLog(String name) {
        int newLineNum = 0;
        int originalFileLine = 0;
        int matchTraceNum = 0;
        String newLog = "";
        for (int i = 0; i < originalLogLocationList.size(); i++) {
            String logLocation = originalLogLocationList.get(0);
            try {
                File oldLogFile = new File(logLocation);
                BufferedReader reader = new BufferedReader(new FileReader(
                        oldLogFile));
                String record = reader.readLine();
                while (record != null) {
                    originalFileLine++;
                    // record = reader.readLine();
                    // System.out.print("\nrecord:"+record);
                    boolean TraceNameMatch = false;
                    ArrayList<String> matchTraceList = new ArrayList<String>();
                    //time
                    if (record == null || !record.contains(",")) {
                        //System.out.print("\nrecord==null||record not contain , :" + record);
                        //  System.out.print("\nreader.readLine() :"+reader.readLine());
                        break;
                    }
                    String[] recordDetail = record.split(",");
                    String recordTimeFull = recordDetail[0];

                    // 循环trace判断是都有符合的trace
                    for (int j = 0; j < traceNameList.size(); j++) {
                        String traceID = traceNameList.get(j);
                        // ArrayList<String> traceNameDetail=new
                        // ArrayList<String>();
                        String[] traceNameDetail = traceID.split(",");
                        //  System.out.print("\ntraceID:" + traceID);
                       
                        // 是否traceID匹配
                        boolean containAll = true;
                        for (int s = 0; s < traceNameDetail.length - 1; s++) {
                            // System.out.print("\ntraceNameDetail[s]"+traceNameDetail[s]);
                            if (!record.contains(traceNameDetail[s])) {
                                containAll = false;
                            }
                        }

                        if (containAll) { // 如果traceName相符，是否在时间范围内

                            TraceNameMatch = true;
                            matchTraceList.add(traceID);
                            // break;
                        }
                    }
                    // 如果traceID相符，是否在时间范围内	
                    if (TraceNameMatch) {
                        matchTraceNum++;
                        Date date = Format.StringToTimeStamp(recordTimeFull);
                        //System.out.print("\ntraceID相符");
                        XFactory factory = XFactoryRegistry.instance().currentDefault();
                        XAttribute attributeTime = factory.createAttributeTimestamp(
                                XTimeExtension.KEY_TIMESTAMP, date,
                                null);
                        String recordTime = attributeTime.toString().substring(0, 19);

                        for (int t = 0; t < matchTraceList.size(); t++) {
                            String traceNameWithBranch = matchTraceList.get(t);
                            if (lastestArrivalMap.get(traceNameWithBranch).compareTo(recordTime) >= 0 && earliestArrivalMap.get(traceNameWithBranch).compareTo(recordTime) <= 0) {
                                //System.out.print("\nin right time zone");
                                //在时间范围内
                                //System.out.print("\nin right time zone");
                                newLog = newLog + record + "\n";
                                newLineNum++;
                            } else {
//                                System.out.print("\n in wrong time zone");
//                                System.out.print("\nbad time:" + recordTime);
//                                System.out.print("\nlastestArrivalMap.get(traceNameWithBranch)" + lastestArrivalMap.get(traceNameWithBranch));
//                                System.out.print("\nearliestArrivalMap.get(traceNameWithBranch)" + earliestArrivalMap.get(traceNameWithBranch));
//                                System.out.print("\nbelong name:" + matchTraceList);
                            }
                        }
                        // System.out.print("\nattributeTime:"+attributeTime);


                        // System.out.print("\nmatch");

                    } else {
                        //System.out.print("\ndo not have match trace,traceNAme:" + record);
                    }
                    record = reader.readLine();
                }

                // System.out.println("\nnewLog:"+newLog);
                BufferedWriter write = new BufferedWriter(new FileWriter(
                        new File(name + ".log")));
                write.write(newLog);
                write.close();
            } catch (Exception e) {
      //          System.out.println("file is not found");
                e.printStackTrace();
            }
        }

 //       System.out.println("\noriginalFileLine:" + originalFileLine);
//        System.out.println("\nnewLineNum:" + newLineNum);
//        System.out.println("\nmatchTraceNum:" + matchTraceNum);
    }

    private static int getLogEventSize(XLog logL) {
        int events = 0;
        XLogInfo info = null;
        info = XLogInfoFactory.createLogInfo(logL);
        events += info.getNumberOfEvents();
        return events;
    }
}
